<?php
require_once("TS3-Framework/TeamSpeak3.php");

class chat2teamspeak
{
	protected $teamspeak = null;
	protected $pluginSettings = null;
	protected $alreadySent = null;
	
	public $arrayStringDelimiter = null;
	
	const NICKNAME_DEFAULT = '@NICKNAME_DEFAULT';
	
	function __construct($tsDisplayNickname='@NICKNAME_DEFAULT', $nicknamePrefix='@NICKNAME_DEFAULT', $nicknameSufix=false)
	{
		if($this->arrayStringDelimiter===null){
			$this->arrayStringDelimiter = '|';
		}
		if($this->alreadySent===null){
			$this->alreadySent = array(
				'message' => array(
					'clientList' => array(),
					'channelList' => array()
				),
				'poke' => array(
					'clientList' => array()
				)
			);
		}
		if($this->pluginSettings===null){
			$this->resetSettings();
		}

		
		
		
		$tsDisplayNicknameFinal = self::nicknameFactory($tsDisplayNickname, $nicknamePrefix, $nicknameSufix);
		include('bf3-chat2teamspeak.cfg.php');
		$exceptionMessage=null;
		$exceptionCount = 0;
		while($exceptionMessage!==false)
		{
			try
			{
				if($exceptionMessage == 'nickname is already in use')
				{
					if($exceptionCount==1){
						$tsDisplayNicknameFinal = self::nicknameFactory($tsDisplayNickname, $nicknamePrefix, $nicknameSufix);
					}
					else{
						$randomPrefix = substr(md5(sha1('lethakmaas').rand(0,9999).microtime()),0,3);
						$tsDisplayNicknameFinal = $randomPrefix.'_'.self::nicknameFactory($tsDisplayNickname, $nicknamePrefix, $nicknameSufix);
					}
				}
				$this->teamspeak = TeamSpeak3::factory("serverquery://".$userName.":".$userPassword."@".$serverHost.":".$serverQueryPort."/?server_port=".$virtualServerPort."&nickname=".urlencode($tsDisplayNicknameFinal)."");
				$exceptionMessage=false;
			}
			catch(Exception $exc0)
			{
				$exceptionMessage=$exc0->getMessage();
				$exceptionCount++;
			}
		}
		return $this;
	}
	
	protected static function nicknameFactory($tsDisplayNickname='@NICKNAME_DEFAULT', $nicknamePrefix='@NICKNAME_DEFAULT', $nicknameSufix=false)
	{
		$tsDisplayNicknameFinal = '';
		if($tsDisplayNickname===null){
			$tsDisplayNickname = self::NICKNAME_DEFAULT;
		}
		if($tsDisplayNickname==self::NICKNAME_DEFAULT){
			$tsDisplayNicknameFinal = 'Battlefield 3';
		}else{
			$tsDisplayNicknameFinal = $tsDisplayNickname;
		}
		if($nicknamePrefix){
			if($nicknamePrefix==self::NICKNAME_DEFAULT){
				$prefixAuto = substr(md5(sha1('lethakmaas').rand(0,9999).microtime()),0,3);
				$tsDisplayNicknameFinal = $prefixAuto.'_'.$tsDisplayNicknameFinal;
			}else{
				$tsDisplayNicknameFinal = $nicknamePrefix.$tsDisplayNicknameFinal;
			}
		}
		if($nicknameSufix){
			if($nicknameSufix==self::NICKNAME_DEFAULT){
				$sufixAuto = substr(md5(sha1('lethakmaas').rand(0,9999).microtime()),0,3);
				$tsDisplayNicknameFinal.= $nicknameSufix.'_'.$sufixAuto;
			}else{
				$tsDisplayNicknameFinal.= $nicknameSufix;
			}
		}
		return $tsDisplayNicknameFinal;
	}
	
	protected function resetSettings()
	{
		$this->defaultPluginSettings = array(
			// Game server related...
			'serverName' => 'string',
			'playerName' => 'string',
			'playerMessage' => 'string',
			// All Users - bypass other broadcast related settings, exept blacklist
			'broadcastPrivateMessageToAllUserEnabled' => 'bool',
			'broadcastPokeToAllUserEnabled' => 'bool',
			// All Channels - bypass other broadcast related settings, exept blacklist
			'broadcastMessageToAllChannelEnabled' => 'bool',
			// Specific Channel
			'broadcastToSpecificChannelEnabled' => 'bool',
			'broadcastToSpecificChannelIDs' => 'arraystring',
			'broadcastToSpecificChannelNames' => 'arraystring',
			// Specific User - Private Message
			'broadcastPrivateMessageToSpecificUserEnabled' => 'bool',
			'broadcastPrivateMessageToSpecificUserIDs' => 'arraystring',
			'broadcastPrivateMessageToSpecificUserNames' => 'arraystring',
			// Specific User - Poke
			'broadcastPokeToSpecificUserEnabled' => 'bool',
			'broadcastPokeToSpecificUserIDs' => 'arraystring',
			'broadcastPokeToSpecificUserNames' => 'arraystring',
			// User in Group - Private Message
			'broadcastPrivateMessageToUserInGroupEnabled' => 'bool',
			'broadcastPrivateMessageToUserInGroupIDs' => 'arraystring',
			'broadcastPrivateMessageToUserInGroupNames' => 'arraystring',
			// User in Group - Poke
			'broadcastPokeToUserInGroupEnabled' => 'bool',
			'broadcastPokeToUserInGroupIDs' => 'arraystring',
			'broadcastPokeToUserInGroupNames' => 'arraystring',
			// User in Channel - Private Message
			'broadcastPrivateMessageToUserInChannelEnabled' => 'bool',
			'broadcastPrivateMessageToUserInChannelIDs' => 'arraystring',
			'broadcastPrivateMessageToUserInChannelNames' => 'arraystring',
			// User in Channel - Poke
			'broadcastPokeToUserInChannelEnabled' => 'bool',
			'broadcastPokeToUserInChannelIDs' => 'arraystring',
			'broadcastPokeToUserInChannelNames' => 'arraystring',
			//All chat
			//'broadcastAllChatToChannelIDs' => 'arraystring',
			// Blacklist - they will never receive the broadcast
			'broadcastBlacklistEnabled' => 'bool',
			'broadcastBlacklistUserIDs' => 'arraystring',
			'broadcastBlacklistGroupIDs' => 'arraystring',
			'broadcastBlacklistChannelIDs' => 'arraystring',
		);
		foreach($this->defaultPluginSettings as $K=>$V)
		{
			switch($V)
			{
				case 'bool':
					$this->pluginSettings[$K] = false;
				break;
				case 'arraystring':
				default:
					$this->pluginSettings[$K] = array();
				break;
			}
		}
		return $this;
	}
	
	protected function getInputSettings($inputs=null)
	{
		if($inputs===null || !is_array($inputs)){
			$inputs = $_POST;
		}
		
		foreach($this->pluginSettings as $varName=>$varValue)
		{
			if(isset($inputs[$varName]))
			{
				switch($this->defaultPluginSettings[$varName])
				{
					case 'bool':
						if(strtolower(trim($inputs[$varName]))=="true")
						{
							$this->pluginSettings[$varName] = true;
						}
						elseif(strtolower(trim($inputs[$varName]))=="false")
						{
							$this->pluginSettings[$varName] = false;
						}
						else
						{
							$this->pluginSettings[$varName] = (bool)(int)trim($inputs[$varName]);
						}
					break;
					case 'arraystring':
						$this->pluginSettings[$varName] = explode($this->arrayStringDelimiter, $inputs[$varName]);
					break;
					default:
						$this->pluginSettings[$varName] = $inputs[$varName];
					break;
				}
			}
		}
		return $this->pluginSettings;
	}
	
	protected function formatMessage($playerMessage=null, $playerName=null, $serverName=null)
	{
		if($playerMessage===null) $playerMessage = $this->pluginSettings['playerMessage'];
		if($playerName===null) $playerName = $this->pluginSettings['playerName'];
		if($serverName===null) $serverName = $this->pluginSettings['serverName'];
		
		$message = '';
		if($serverName!==null){
			$message.= ' ['.$serverName.']';
		}
		if($playerName!==null){
			$message.= ' <'.$playerName.'>';
		}
		if($playerMessage!==null){
			$message.= ' '.$playerMessage.'';
		}
		return $message;
	}
	
	protected function isBlacklisted($user)
	{
		if($this->pluginSettings['broadcastBlacklistEnabled'] && ($user instanceof TeamSpeak3_Node_Client))
		{
			if( in_array($user['client_database_id'], $this->pluginSettings['broadcastBlacklistUserIDs']) ) return true;
			try
			{
				$userChannel = $user['cid'];
				if( in_array($userChannel, $this->pluginSettings['broadcastBlacklistChannelIDs']) ) return true;
				
				$userGroups = $user->memberOf();
				foreach($userGroups as $userGroup){
					if( in_array($userGroup->getId(), $this->pluginSettings['broadcastBlacklistGroupIDs']) ) return true;
				}
			}
			catch(Exception $exc){}
		}
		return false;
	}
	
	protected function isInGroup($user, $groupIDs)
	{
		if(is_array($groupIDs))
		{
			try
			{
				$userGroups = $user->memberOf();
				foreach($userGroups as $userGroup){
					if( in_array($userGroup->getId(), $groupIDs) ) return true;
				}
			}
			catch(Exception $exc){}
		}
		elseif($groupIDs=='bypass')
		{
			return true;
		}
		return false;
	}
	
	protected function isInChannel($user, $channelIDs)
	{
		if(is_array($channelIDs))
		{
			try
			{
				$userChannel = $user['cid'];
				if( in_array($userChannel, $channelIDs) ) return true;
			}
			catch(Exception $exc){}
		}
		elseif($channelIDs=='bypass')
		{
			return true;
		}
		return false;
	}
	
	protected function broadcastToUsers($userIDs='all', $broadcastMethod='message', $groupIds='bypass', $channelIDs='bypass', $playerMessage=null, $playerName=null, $serverName=null)
	{
		$exceptions = array();
		if($broadcastMethod!=='poke'){
			$broadcastMethod = 'message';
		}
		try
		{
			$fullClientList = $this->teamspeak->clientList();
			if($userIDs!==null && is_array($userIDs)){
				foreach($fullClientList as $clientListKey => $clientListValue){
					if(in_array($clientListValue['client_database_id'], $userIDs, false)){
						$clientList[] = $clientListValue;
					}
				}
			}
			elseif($userIDs=='all'){
				$clientList = $fullClientList;
			}
			if($clientList===null){
				$clientList = array();
			}
			$message = $this->formatMessage($playerMessage, $playerName, $serverName);
			foreach($clientList as $user)
			{	
				// No broadcast if one of those conditions are met.
				if($this->isBlacklisted($user)) continue;
				if(!$this->isInGroup($user, $groupIds)) continue;
				if(!$this->isInChannel($user, $channelIDs)) continue;
				if(in_array($user['client_database_id'], $this->alreadySent[$broadcastMethod]['clientList'])) continue;
				
				// Trying to broadcast...
				try{
					$user->$broadcastMethod($message);
					$this->alreadySent[$broadcastMethod]['clientList'][] = $user['client_database_id'];
				}
				catch(Exception $exc1){$exceptions[] = $exc1->getMessage();}
			}
		}
		catch(Exception $exc) {$exceptions[] = $exc->getMessage();}
		return $exceptions;
	}
	
	protected function broadcastMessageToChannels($channelIDs='all', $playerMessage=null, $playerName=null, $serverName=null)
	{
		$exceptions = array();
		$channelList = array();
		try
		{
			$fullChannelList = $this->teamspeak->channelList();
			if($channelIDs!==null && is_array($channelIDs))
			{
				foreach($fullChannelList as $channelListKey => $channelListValue){
					if(in_array($channelListValue->getId(), $channelIDs, false)){
						$channelList[] = $channelListValue;
					}
				}
			}
			elseif($channelIDs=='all')
			{
				$channelList = $fullChannelList;
			}else{
				$channelList = array();
			}
			
			$message = $this->formatMessage($playerMessage, $playerName, $serverName);
			foreach($channelList as $channel)
			{
				// No broadcast if one of those conditions are met.
				if( $this->pluginSettings['broadcastBlacklistEnabled'] && in_array($channel->getId(), $this->pluginSettings['broadcastBlacklistChannelIDs']) ) continue;
				if(in_array($channel->getId(), $this->alreadySent['message']['channelList'])) continue;
				
				// Trying to broadcast...
				try{
					$channel->message($message);
					$this->alreadySent['message']['channelList'][] = $channel->getId();
				}
				catch(Exception $exc1){
					$exceptions[] = $exc1->getMessage();
				}
			}
		}
		catch(Exception $exc)
		{
			$exceptions[] = $exc->getMessage();
		}
		return $exceptions;
	}
	
	protected function broadcastToSpecificChannelNames($nameList=null, $playerMessage=null, $playerName=null, $serverName=null)
	{
		if($nameList===null || !is_array($nameList)){
			$nameList = array();
		}
		if(count($nameList)>0)
		{
			$IDs = array();
			$fullChannelList = $this->teamspeak->channelList();
			foreach($fullChannelList as $channel){
				if(in_array($channel['channel_name'], $nameList, false)){
					$IDs[] = $channel->getId();
				}
			}
			if(count($IDs)>0) return $this->broadcastMessageToChannels($IDs, $playerMessage, $playerName, $serverName);
		}
		return null;
	}
	
	protected function broadcastToSpecificUserNames($nameList=null, $broadcastMethod='message',   $groupIds='bypass', $channelIDs='bypass', $playerMessage=null, $playerName=null, $serverName=null)
	{
		if($nameList===null || !is_array($nameList)){
			$nameList = array();
		}
		if(count($nameList)>0)
		{
			$IDs = array();
			$fullClientList = $this->teamspeak->clientList();
			foreach($fullClientList as $client){
				if(in_array($client['client_nickname'], $nameList, false)){
					$IDs[] = $client["client_database_id"];
				}
			}
			if(count($IDs)>0) return $this->broadcastToUsers($IDs, $broadcastMethod,  $groupIds, $channelIDs, $playerMessage, $playerName, $serverName);
		}
		return null;
	}
	
	protected function broadcastToUserInGroups($IDs=null, $broadcastMethod='message', $playerMessage=null, $playerName=null, $serverName=null)
	{
		return $this->broadcastToUsers('all', $broadcastMethod , $IDs, 'bypass', $playerMessage, $playerName, $serverName);
	}
	protected function broadcastToUserInGroupNames($nameList=null, $broadcastMethod='message', $playerMessage=null, $playerName=null, $serverName=null)
	{
		throw new Exception('NotImplementedMethod::broadcastToUserInGroupNames');
	}
	
	protected function broadcastToUserInChannels($IDs=null, $broadcastMethod='message', $playerMessage=null, $playerName=null, $serverName=null)
	{
		return $this->broadcastToUsers('all', $broadcastMethod, 'bypass', $IDs, $playerMessage, $playerName, $serverName);
	}
	protected function broadcastToUserInChannelNames($nameList=null, $broadcastMethod='message', $playerMessage=null, $playerName=null, $serverName=null)
	{
		throw new Exception('NotImplementedMethod::broadcastToUserInChannelNames');
	}

	public function process()
	{
		$cfg = $this->getInputSettings();
		$canContinue = true;
		
		/*if(count($cfg['broadcastAllChatToChannelIDs'])){
			$this->broadcastMessageToChannels($cfg['broadcastAllChatToChannelIDs']);
			$canContinue = false;
		}*/
		if($cfg['broadcastPrivateMessageToAllUserEnabled']){
			$this->broadcastToUsers('all', 'message');
			$canContinue = false;
		}
		if($cfg['broadcastPokeToAllUserEnabled']){
			$this->broadcastToUsers('all', 'poke');
			$canContinue = false;
		}
		if($cfg['broadcastMessageToAllChannelEnabled'] && $canContinue){
			$this->broadcastMessageToChannels('all');
			$canContinue = false;
		}
		if($cfg['broadcastToSpecificChannelEnabled'] && $canContinue){
			$this->broadcastMessageToChannels($cfg['broadcastToSpecificChannelIDs']);
			$this->broadcastToSpecificChannelNames($cfg['broadcastToSpecificChannelNames']);
		}
		if($cfg['broadcastPrivateMessageToSpecificUserEnabled'] && $canContinue){
			$this->broadcastToUsers($cfg['broadcastPrivateMessageToSpecificUserIDs'], 'message');
			$this->broadcastToSpecificUserNames($cfg['broadcastPrivateMessageToSpecificUserNames'], 'message');
		}
		if($cfg['broadcastPokeToSpecificUserEnabled'] && $canContinue){
			$this->broadcastToUsers($cfg['broadcastPokeToSpecificUserIDs'], 'poke');
			$this->broadcastToSpecificUserNames($cfg['broadcastPokeToSpecificUserNames'], 'poke');
		}
		if($cfg['broadcastPrivateMessageToUserInGroupEnabled'] && $canContinue){
			$this->broadcastToUserInGroups($cfg['broadcastPrivateMessageToUserInGroupIDs'], 'message');
			//$this->broadcastToUserInGroupNames($cfg['broadcastPrivateMessageToUserInGroupNames'], 'message');
		}
		if($cfg['broadcastPokeToUserInGroupEnabled'] && $canContinue){
			$this->broadcastToUserInGroups($cfg['broadcastPokeToUserInGroupIDs'], 'poke');
			//$this->broadcastToUserInGroupNames($cfg['broadcastPokeToUserInGroupNames'], 'poke');
		}
		if($cfg['broadcastPrivateMessageToUserInChannelEnabled'] && $canContinue){
			$this->broadcastToUserInChannels($cfg['broadcastPrivateMessageToUserInChannelIDs'], 'message');
			//$this->broadcastToUserInChannelNames($cfg['broadcastPrivateMessageToUserInChannelNames'], 'message');
		}
		if($cfg['broadcastPokeToUserInChannelEnabled'] && $canContinue){
			$this->broadcastToUserInChannels($cfg['broadcastPokeToUserInChannelIDs'], 'poke');
			//$this->broadcastToUserInChannelNames($cfg['broadcastPokeToUserInChannelNames'], 'poke');
		}
		var_dump($cfg);exit;
	}
	
}

//EXECUTION/////////////////////////////
try{
	$c2t = new chat2teamspeak(chat2teamspeak::NICKNAME_DEFAULT, false, false);
}
catch(Exception $exc){
	$trace=$exc->getTrace();
	echo '<hr>'.$exc->getMessage().'<pre>'.print_r($trace[0],true).'</pre><hr>';exit;
}
$c2t->process();




?>